package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.config.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.entity.dto.DishDto;
import com.itheima.reggie.entity.dto.PageQueryDto;
import com.itheima.reggie.mapper.DishFlavorMapper;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import com.itheima.reggie.web.exception.BusinessException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Name DishServiceImpl
 * @Author BaiXin
 * @Date 2022-11-02 10:02
 */
@Service
@Transactional//开启事务
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishFlavorService dishFlavorService;

    /**
     * 新增菜品，包括菜品和口味并检查菜品名是否重复
     *
     * @param dishDto 要新增的菜品信息DTO对象
     * @return 是否新增成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)//当运行时异常发生，默认事务不回滚，这样才会设置为回滚
    public Boolean saveWithCheckNameAndSaveFlavors(DishDto dishDto) {
        //检查菜品名称是否重复
        checkDishName(dishDto);
        //保存菜品基本信息
        dishMapper.insert(dishDto);
        Long dishId = dishDto.getId();
        //获取口味信息，遍历
        List<DishFlavor> flavors = dishDto.getFlavors();
        //保存菜品口味信息
        for (DishFlavor flavor : flavors) {
            //获取菜品id
            flavor.setDishId(dishId);
            dishFlavorMapper.insert(flavor);
        }
        //组织数据并返回
        return true;
    }

    /**
     * 分页查询
     *
     * @param pageQueryDto 分页查询条件
     * @return 分页对象
     */
    @Override
    public Page<Dish> pageOrigin(PageQueryDto pageQueryDto) {
        //分页构造
        Page<Dish> dishPage = new Page<>(pageQueryDto.getPage(), pageQueryDto.getPageSize());

        //查询条件
        LambdaQueryWrapper<Dish> qw = Wrappers.lambdaQuery(Dish.class);
        String name = pageQueryDto.getName();
        qw.like(name != null, Dish::getName, name)
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime);

        //查询
        Page<Dish> page = dishMapper.selectPage(dishPage, qw);

        //组织数据返回
        return page;
    }

    /**
     * 分页查询包含菜品分类名称
     *
     * @param pageQueryDto 分页查询条件
     * @return 分页对象
     */
    @Override
    public Page<DishDto> page(PageQueryDto pageQueryDto) {
        //分页构造
        Page<Dish> dishPage = new Page<>(pageQueryDto.getPage(), pageQueryDto.getPageSize());

        //查询条件
        LambdaQueryWrapper<Dish> qw = Wrappers.lambdaQuery(Dish.class);
        String name = pageQueryDto.getName();
        qw.like(name != null, Dish::getName, name)
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime);

        //查询
        dishMapper.selectPage(dishPage, qw);

        //新建新的page对象
        Page<DishDto> dishDtoPage = new Page<>();

        /*
        page<Dish> page<DishDto>
            当前页
            总页数
            总记录数
            页面大小
            records:list<Dish>               List<DishDto>
        */
        //复制
        BeanUtils.copyProperties(dishPage, dishDtoPage, "records");


        //复制records
        //获取dishPage中的records
        List<Dish> dishes = dishPage.getRecords();

        //创建DishDto 的 list对象
        ArrayList<DishDto> dishDtos = new ArrayList<>();
        //查询所有菜品分类名称，降低mysql服务器压力，
        List<Category> categories = categoryService.findByType(1);

        for (Dish dish : dishes) {
            DishDto dishDto = new DishDto();
            //复制基本信息
            BeanUtils.copyProperties(dish, dishDto);
            for (Category category : categories) {
                //判断id是否相同
                if (category.getId().equals(dish.getCategoryId())) {
                    //id相同，设置
                    dishDto.setCategoryName(category.getName());
                    break;
                }
            }
            dishDtos.add(dishDto);
        }
        dishDtoPage.setRecords(dishDtos);
        return dishDtoPage;
    }

    /**
     * 根据id查询菜品详情
     *
     * @param id 菜品id
     * @return 菜品dto对象
     */
    @Override
    public DishDto findById(Long id) {
        //根据id查询dish（基本信息）
        Dish dish = dishMapper.selectById(id);
        if (id != null) {
            //根据菜品id查询口味信息
            Wrapper<DishFlavor> qw = Wrappers.lambdaQuery(DishFlavor.class)
                    .eq(DishFlavor::getDishId, id);
            List<DishFlavor> dishFlavors = dishFlavorMapper.selectList(qw);
            //封装口味信息到菜品dto对象返回
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish, dishDto);
            dishDto.setFlavors(dishFlavors);
            return dishDto;
        }
        return null;
    }

    /**
     * 更新
     *
     * @param dishDto 新的菜品对象
     * @return 操作是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateByIdWithFlavors(DishDto dishDto) {

        // 名称重复检查
        checkDishName(dishDto);

        // 保存菜品基本信息
        int result = dishMapper.updateById(dishDto);

        // 保存菜品口味信息，先删后加
        if (result > 0) {
            // 删除现有口味
            Long dishId = dishDto.getId();
            Wrapper<DishFlavor> qw =
                    Wrappers.lambdaQuery(DishFlavor.class)
                            .eq(DishFlavor::getDishId, dishId);
            dishFlavorMapper.delete(qw);

            // 保存新的口味信息。
            List<DishFlavor> flavors = dishDto.getFlavors();

            // 为了保证数据完整性，统一为口味重新设置菜品id
            for (DishFlavor flavor : flavors) {
                flavor.setDishId(dishId);
                dishFlavorMapper.insert(flavor);
            }

            // 组织数并返回
            // 成功
            return true;
        }
        return false;
    }

    /**
     * 批量修改状态
     *
     * @param status 修改状态值
     * @param ids
     * @return
     */
    @Override
    public boolean switchStatus(Integer status, Long[] ids) {
        // 遍历所有id，挨个更新
        // update dish set status  = #{status }  where id in (1,2,3,4)
        int count = dishMapper.updateByIds(status, ids);
        return count > 0;
    }

    /**
     * 根据条件查询菜品
     *
     * @param dish 菜品条件
     * @return 菜品基本数据
     */
    @Override
    public List<Dish> findByCondition(Dish dish) {
        //参数处理
        if (dish.getStatus() == null) {
            dish.setStatus(1);
        }
        //条件构造
        Wrapper<Dish> qw = Wrappers.lambdaQuery(Dish.class)
                .like(dish.getName() != null, Dish::getName, dish.getName())
                .eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId())
                .eq(dish.getId() != null, Dish::getId, dish.getId())
                .eq(Dish::getStatus, dish.getStatus())
                .like(dish.getDescription() != null, Dish::getDescription, dish.getDescription())
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime);

        //查询
        List<Dish> dishes = dishMapper.selectList(qw);
        //返回
        return dishes;
    }

    /**
     * 根据条件查询菜品 包括菜品口味信息
     *
     * @param dish 菜品条件
     * @return 菜品基本数据
     */
    @Override
    public List<DishDto> findByConditionAndDishFlavors(Dish dish) {
        //参数处理
        if (dish.getStatus() == null) {
            dish.setStatus(1);
        }
        //条件构造
        Wrapper<Dish> qw = Wrappers.lambdaQuery(Dish.class)
                .like(dish.getName() != null, Dish::getName, dish.getName())
                .eq(dish.getCategoryId() != null, Dish::getCategoryId, dish.getCategoryId())
                .eq(dish.getId() != null, Dish::getId, dish.getId())
                .eq(Dish::getStatus, dish.getStatus())
                .like(dish.getDescription() != null, Dish::getDescription, dish.getDescription())
                .orderByAsc(Dish::getSort)
                .orderByDesc(Dish::getUpdateTime);

        //查询
        List<Dish> dishes = dishMapper.selectList(qw);


        List<DishDto> dishDtoList = dishes.stream().map(dish1 -> {
            Long dish1Id = dish1.getId();

            Wrapper<DishFlavor> qw1 = Wrappers.lambdaQuery(DishFlavor.class)
                    .eq(DishFlavor::getDishId, dish1Id);
            List<DishFlavor> dishFlavors = dishFlavorService.list(qw1);

            //新建dishDto复制数据
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(dish1, dishDto);

            dishDto.setFlavors(dishFlavors);

            return dishDto;
        }).collect(Collectors.toList());
        //返回
        return dishDtoList;
    }


    /**
     * 检查菜品名称是否重复
     *
     * @param dishDto
     * @return
     */
    private boolean checkDishName(DishDto dishDto) {
        LambdaQueryWrapper<Dish> qw = Wrappers
                .lambdaQuery(Dish.class)
                .eq(Dish::getName, dishDto.getName())
                .ne(dishDto.getId() != null, Dish::getId, dishDto.getId());
        Dish dish = dishMapper.selectOne(qw);
        if (dish != null) {
            //已经存在
            throw new BusinessException("该菜品名称已经存在，请修改后重试");
        }
        return false;
    }
}
